package com.quectel.constant.core.propertybill;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

/**
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/4/6 9:24
 * @description new java file header...
 */
public class PropertyBillConstants {

    public static final Pair<String, String> DUE_DATE_SLOT_KEY_PAIR = ImmutablePair.of("startDueDate", "endDueDate");
    public static final Pair<String, String> START_DATE_SLOT_KEY_PAIR = ImmutablePair.of("startDateBegin", "startDateEnd");
    public static final String BINDING_IDS = "bindingIds";
    public static final String ROOM_IDS = "roomIds";
    public static final String TODAY = "today";
    public static final String START_DATE_FLAG = "startDateFlag";
    /**
     * 按创建时间排序的key
     */
    public static final String CREATE_TIME_ORDER_KEY = "create_time";
    /**
     * 按支付时间排序的key
     */
    public static final String PAY_TIME_ORDER_KEY = "pay_time";

    /**
     * 字典值:物业收费标准收费周期
     */
    public static final String PROPERTY_CHARGEABLE_LIST_CYCLE_TYPE = "PropertyChargeableListCycleType";
    /**
     * 字段值:物业活动优惠方式
     */
    public static final String PROPERTY_ACTIVITY_METHOD = "PropertyActivityMethod";
    /**
     * 物业账单操作锁
     */
    public static final Function<Long, String> BILL_OPERATE_LOCK_FUNC = billId -> "BILL_OPERATE_LOCK:" + billId;

    /**
     * 待支付订单状态
     * 待支付,支付中,支付失败
     */
    public static final List<Byte> NOT_PAY_STATUS_LIST = new ArrayList<>(Arrays.asList(
            PayStatus.CANCEL.getStatusValue(),
            PayStatus.INIT.getStatusValue()


    ));


    /**
     * 已支付订单状态
     * 支付成功,支付失败,退款中,部分退款,全额退款,退款失败
     */
    public static final List<Byte> PAID_STATUS_LIST = new ArrayList<>(Arrays.asList(
            PayStatus.PAY_SUCCESS.getStatusValue()
    ));

    /**
     * 订单状态
     */
    @AllArgsConstructor
    public enum MsgType {
        /**
         * 新增
         */
        ADD(new Byte("1")),
        /**
         * 逾期
         */
        OVERDUE(new Byte("2")),
        ;
        @Getter
        @Setter
        private Byte type;
    }


    /**
     * 订单状态
     */
    @AllArgsConstructor
    public enum PayStatus {
        /**
         * 取消
         */
        CANCEL(new Byte("-1")),
        /**
         * 初始化
         */
        INIT(new Byte("0")),

        /**
         * 支付成功
         */
        PAY_SUCCESS(new Byte("1"));
        @Getter
        @Setter
        private Byte statusValue;
    }


    @AllArgsConstructor
    public enum ActivityGroupType {
        /**
         * 折扣项目
         */
        DISCOUNT_ITEM((byte) 1),
        /**
         * 礼品
         */
        GIFT((byte) 2),
        ;

        @Getter
        private Byte type;
    }

    @AllArgsConstructor
    public enum DiscountType {

        /**
         * 折扣
         */
        DISCOUNT((byte) 1) {
            @Override
            public BigDecimal calculate(BigDecimal itemAmount, BigDecimal amount) {
                //折扣,前端填写的是百分比10% ,则优惠10%,乘上0.01,amount是百分比单位
                return itemAmount.multiply(amount).multiply(BigDecimal.valueOf(0.01));
            }
        },

        /**
         * 扣除金额
         */
        DEDUCTION((byte) 2) {
            @Override
            public BigDecimal calculate(BigDecimal itemAmount, BigDecimal amount) {
                return amount;
            }
        },
        ;

        @Getter
        private Byte type;

        public abstract BigDecimal calculate(BigDecimal itemAmount, BigDecimal amount);

        public static DiscountType getByType(Byte type) {
            for (DiscountType discountType : DiscountType.values()) {
                if (discountType.getType().equals(type)) {
                    return discountType;
                }
            }
            return null;
        }


    }

    @AllArgsConstructor
    public enum OverdueStatus {

        /**
         * 未逾期
         */
        NOT_OVERDUE((byte) 0),

        /**
         * 已逾期
         */
        OVERDUE((byte) 1),
        ;

        @Getter
        private Byte status;

    }


    @AllArgsConstructor
    public enum PropertyChargeableItemMethod {

        /**
         * 面积每天
         */
        AREA_PER_DAY((byte) 1) {
            @Override
            public BigDecimal calculate(BigDecimal unit, BigDecimal area, Long timeLength) {
                return unit.multiply(area).multiply(BigDecimal.valueOf(timeLength));
            }
        },
        /**
         * 面积每月
         */
        AREA_PER_MONTH((byte) 2) {
            @Override
            public BigDecimal calculate(BigDecimal unit, BigDecimal area, Long timeLength) {
                return unit.multiply(area).multiply(BigDecimal.valueOf(timeLength));
            }
        },
        /**
         * 固定每天
         */
        FIXED_AMOUNT_PER_DAY((byte) 3) {
            @Override
            public BigDecimal calculate(BigDecimal unit, BigDecimal area, Long timeLength) {
                return unit.multiply(BigDecimal.valueOf(timeLength));
            }
        },
        /**
         * 固定每月
         */
        FIXED_AMOUNT_PER_MONTH((byte) 4) {
            @Override
            public BigDecimal calculate(BigDecimal unit, BigDecimal area, Long timeLength) {
                return unit.multiply(BigDecimal.valueOf(timeLength));
            }
        },

        ;

        @Getter
        private Byte method;

        public abstract BigDecimal calculate(BigDecimal unit, BigDecimal area, Long timeLength);

        public static PropertyChargeableItemMethod getByMethod(Byte method) {
            for (PropertyChargeableItemMethod propertyChargeableItemMethod : PropertyChargeableItemMethod.values()) {
                if (propertyChargeableItemMethod.getMethod().equals(method)) {
                    return propertyChargeableItemMethod;
                }
            }
            return null;
        }


    }

    @AllArgsConstructor
    public enum TimeUnitEnum {
        /**
         * 秒
         */
        SECOND((byte) 1),
        /**
         * 小时
         */
        HOUR((byte) 2),
        /**
         * 天
         */
        DAY((byte) 3),
        /**
         * 周
         */
        WEEK((byte) 4),
        /**
         * 月
         */
        MONTH((byte) 5),
        /**
         * 季节
         */
        SEASON((byte) 6),
        /**
         * 年
         */
        YEAR((byte) 7),
        ;

        @Getter
        private Byte unit;

        public static TimeUnitEnum getByUnit(Byte unit) {
            for (TimeUnitEnum typeEnum : TimeUnitEnum.values()) {
                if (typeEnum.getUnit().equals(unit)) {
                    return typeEnum;
                }
            }
            return null;
        }


    }

    @AllArgsConstructor
    public enum PropertyChargeableListCycleTypeEnum {
        /**
         * 月付
         */
        MONTH((byte) 1),
        /**
         * 季
         */
        SEASON((byte) 2),
        /**
         * 半年
         */
        HALF_YEAR((byte) 3),
        /**
         * 年
         */
        YEAR((byte) 4),
        ;

        @Getter
        private Byte type;

        public static PropertyChargeableListCycleTypeEnum getByType(Byte type) {
            for (PropertyChargeableListCycleTypeEnum typeEnum : PropertyChargeableListCycleTypeEnum.values()) {
                if (typeEnum.getType().equals(type)) {
                    return typeEnum;
                }
            }
            return null;
        }

    }


}
